Week 8 — Input Devices

OCt 29, 2025 · PCB Time of Flight Distance Sensor Fusion 360

Consider what my final project needs, I decided to add another PCB note here. This week is about make a distance sensor that measures, well, distance, and hopefully could distance the change on a display. The sensor I'm getting is VL53L1X. I like this sensor as it had marked down which pin is which.(After some homework on how this sensor works. I reached the conclusion I only needed four pins to make it work: VDD, GND, SDA, SCL)

I downloaded XIAO ESP32S3 Pinlist and VL53L1X Pinlist to help me with the PCB design

VL53L1X Pin Overview

On the VL53L1X there are six pins: VIN, GND, SCL, SDA, GPIO, and XSHUT. It can be a bit overwhelming if you’ve never seen these before, so I looked them up and summarized what each one does:

VIN
Power input, usually 3.3V or 5V.
GND
Ground reference – must be connected to the microcontroller’s GND.
SCL
I²C clock line – connect to the microcontroller’s SCL pin. The microcontroller controls the clock pulses on this line.
SDA
I²C data line – connect to the microcontroller’s SDA pin.
All data (commands and readings) flows through this line.
Together, SCL and SDA form the entire I²C communication interface.
GPIO
A general-purpose output from the sensor. This pin is optional and can be used, for example, as an interrupt output.
XSHUT
Shutdown pin (active-low hardware reset).
Pull LOW → the sensor shuts down.
Pull HIGH (3.3V) → the sensor wakes up.

Preparation

One library needs to be installed before the real programing - VL53L1X.h

Even with simple wire connection, I run into an unexpcted problem. I wrote a program that scan the address on the sensor and the result came back shocked me. It seems the system detected 120+ devices.

How can this be? I did some research, and even though I could not be sure, but it is based on this theory that I eventually solved the issue. It seems the wire I used was too long, which means the HIGH and LOW are no longer really HIGH and LOW but somewhere floating, creating a lot of noise. So I changed to short wires, and problem gone. Now it's showing only one device! (At the address of 0x29)

Now I have one device found, not 120+
Arduino / C++ Scanning for device (Debug with ChatGPT)

      #include <Wire.h>

      // Change these if you’re on a board where you can re-map I2C pins (ESP32, etc.)
      #ifndef SDA
      #define SDA -1
      #endif
      #ifndef SCL
      #define SCL -1
      #endif

      static const uint8_t VL53_ADDR = 0x29;

      // ---- Low-level I2C helpers for VL53L1X register access ----
      // VL53L1X uses 16-bit register addresses.
      bool writeReg16(uint8_t addr, uint16_t reg, uint8_t value) {
        Wire.beginTransmission(addr);
        Wire.write((uint8_t)(reg >> 8));
        Wire.write((uint8_t)(reg & 0xFF));
        Wire.write(value);
        return (Wire.endTransmission() == 0);
      }

      bool readReg8(uint8_t addr, uint16_t reg, uint8_t &out) {
        Wire.beginTransmission(addr);
        Wire.write((uint8_t)(reg >> 8));
        Wire.write((uint8_t)(reg & 0xFF));
        if (Wire.endTransmission(false) != 0) {
          return false;
        }

        int n = Wire.requestFrom((int)addr, 1);
        if (n != 1) return false;

        out = Wire.read();
        return true;
      }

      void i2cScan() {
        Serial.println("=== I2C scan ===");
        int found = 0;

        for (uint8_t a = 1; a < 127; a++) {
          Wire.beginTransmission(a);
          uint8_t err = Wire.endTransmission();
          if (err == 0) {
            Serial.print("  Found device at 0x");
            if (a < 16) Serial.print("0");
            Serial.println(a, HEX);
            found++;
          }
        }

        Serial.print("Total I2C devices: ");
        Serial.println(found);
        Serial.println("=== I2C scan end ===\n");
      }

      void setup() {
        Serial.begin(115200);
        delay(800);
        Serial.println("\nVL53L1X I2C + ID Test\n");

        Wire.begin();
        Wire.setClock(400000);

        i2cScan();

        Serial.println("Checking for device at 0x29...");
        Wire.beginTransmission(VL53_ADDR);
        uint8_t err = Wire.endTransmission();
        Serial.print("  endTransmission returned: ");
        Serial.println(err);

        if (err != 0) {
          Serial.println("\n❌ No ACK from 0x29.\n");
          return;
        }

        Serial.println("✅ 0x29 ACKed.\n");

        Serial.println("Reading Model ID (reg 0x010F)...");
        uint8_t modelId = 0;
        bool ok = readReg8(VL53_ADDR, 0x010F, modelId);

        if (!ok) {
          Serial.println("❌ Failed to read Model ID.");
          return;
        }

        Serial.print("✅ Model ID read: 0x");
        Serial.println(modelId, HEX);
      }

      void loop() {
        delay(3000);
        i2cScan();
      }
      
Since the connection is very simple, and I had a major setback on the soldering the board. I decided to just connect the two electronics with simple wire and write program to see if this thing works. It went really surprisingly smooth. It worked, even though with a few caveats that I will mention later.
The intial program had a refresh rate or loop delay set too high. So I lowered it quite a bit for myself to track it.
Now that I know for sure the sensor works and I understand the pins right. I milled the board using Bantam in the Lab.
Board soldering complete

Initial Observations (Distance Sensor Test)

1) Readings were not perfectly constant (mm-level jitter)

Even though the sensor was placed on a stable table and measured the distance to the room ceiling, the returned values were not identical each time.

  • The readings were largely consistent, but each measurement still varied by a few millimeters.
  • This suggests the sensor has a small but noticeable measurement error / noise under real conditions.

2) “Zero” was reported before physical contact

When I moved my hand close to the sensor, it did not need to physically touch the sensor for the reading to become zero. I could get a reading of 0 even when my palm was still approximately 3–4 cm away.

  • This suggests there may be a minimum measurable range or clamping behavior.
  • My hypothesis: below a certain threshold distance, the sensor reports 0 (no negative values).
  • In other words, the displayed value may behave like: max(0, real_distance - threshold)
Sensor File Thumbnail
Spec file for file VL53L1X
Arduino / C++ OLED SSD1306 TEST (Counter)

      #include <Wire.h>
      #include <Adafruit_GFX.h>
      #include <Adafruit_SSD1306.h>

      #define SCREEN_WIDTH 128
      #define SCREEN_HEIGHT 64
      #define OLED_RESET -1
      #define OLED_ADDR 0x3C

      Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

      void setup() {
        Serial.begin(115200);

        // Use board default I2C pins
        Wire.begin();
        Wire.setClock(100000);

        if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
          Serial.println("SSD1306 init failed");
          while (true) delay(10);
        }

        display.clearDisplay();
        display.display();

        Serial.println("OLED initialized");
      }

      void loop() {
        static uint32_t counter = 0;

        display.clearDisplay();

        // Visual proof it works
        display.drawRect(0, 0, 128, 64, SSD1306_WHITE);
        display.fillRect(5, 5, 30, 20, SSD1306_WHITE);

        display.setTextColor(SSD1306_WHITE);
        display.setTextSize(2);
        display.setCursor(45, 10);
        display.println("TEST");

        display.setTextSize(1);
        display.setCursor(45, 40);
        display.print("Count: ");
        display.println(counter++);

        display.display();
        delay(200);
      }